import threading, Queue, random, thread
from math import *
from human_control import *
from agent_controller import *
from graphics_engine import *
from world_model import *
from agent import *
from agent_logger import *
from sensor_range_finder import *
from sensor_pie_slices import *
from sensor_radar import *
from sensor_node_radar import *
from sensor_nclosest_radar import *
from agent_nn import *
import time
# Initialize world, game, IO, control_queue,etc
control_queue=Queue.Queue()
main_graphics_engine=graphics_engine()
main_graphics_engine.start_event_loop()
main_world_model=world_model(main_graphics_engine,[(240,300,240,400)])

# Create Agents, put them in a dict indexed by number, pass them to agent_controller, initialize them with world_model
temp_agents={}
temp_actions={'move_rel_world':main_world_model.agent_move_rel_world,'move_rel_agent':main_world_model.agent_move_rel_agent,'turn_rel':main_world_model.agent_turn_rel}

positions=[[220,350],[260,350]]
headings=[0,pi]
for i in xrange(2):
	range_finder=sensor_range_finder(i, main_world_model, [0], 2000)
	
	nclosest_radar=sensor_nclosest_radar(i,main_world_model,1)
	if i==0:
		if 1:
			temp_agents[i]=agent_logger(actions=temp_actions,senses={'range_finder':range_finder.sense, 'nclosest_radar':nclosest_radar.sense},agent_num=i)
		else:
			temp_agents[i]=agent_nn(actions=temp_actions,senses={'range_finder':range_finder.sense, 'nclosest_radar':nclosest_radar.sense},agent_num=i)
	else:
		temp_agents[i]=agent(actions=temp_actions,senses={'range_finder':range_finder.sense, 'nclosest_radar':nclosest_radar.sense},agent_num=i)
	main_world_model.new_agent(i,positions[i],headings[i])

main_agent_controller=agent_controller(temp_agents)
main_human_control=human_control(tk_root=main_graphics_engine.tk_root,control_queue=control_queue,agent_controller=main_agent_controller,world_model=main_world_model)
# This is the main thread's processing loop
while main_graphics_engine.mainloop_thread.isAlive():
	# Process human input events
	try:
		temp_fun=control_queue.get(block=False)
		temp_fun()
	except Queue.Empty:
		time.sleep(2)
	main_world_model.seek(0,[0,0])
	for agent in temp_agents.itervalues():
		agent.think()
		
main_graphics_engine.mainloop_thread.join()

def flatten(seq):
  res = []
  for item in seq:
    if (isinstance(item, (tuple, list))):
      res.extend(flatten(item))
    else:
      res.append(item)
  return res

def flatten_log(log_list):
	inputs=[]
	outputs=[]
	for i in range(len(log_list)):
		tmp_input=list(flatten(log_list[i][0].values()[0]))
		outputs.append(tmp_input[1:]) # NOTE This removes the agent number, the need for this will eventually vanish, and thus this should be removed
		inputs.append(flatten(log_list[i][1].values()))
	return inputs,outputs
def load_log(file_name):
	f=file(file_name,'r')
	tmp=pickle.load(f)
	f.close()
	return tmp

def load_flatten(file_name):
	return flatten_log(load_log(file_name))

def combine_logs(log0,log1):
	return [log0[0]+log1[0],log0[1]+log1[1]]

def combine_many_logs(log_name_list):
	is_first=True
	a=0
	for log in log_name_list:
		if is_first:
			a=load_flatten(log)
			is_first=False
		else:
			a=combine_logs(a,load_flatten(log))
	return a
